package com.fjwt.gz.coupon.yspay.yspayutil;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.aliyun.oss.ServiceException;
import com.fjwt.gz.coupon.yspay.YspayIsvParams;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class YsParamUtil {


    /**
     * 格式化当前日期时间字符串
     *
     * @return
     */
    static String getCurrentDateTime(String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(new Date());
    }

    /**
     * 公共参数
     **/
    public static TreeMap<String, String> buildMchBasicMap(YspayIsvParams isvParams, String method){
        TreeMap<String, String> params = new TreeMap<String, String>();
        //接口方法名，根据接口文档取值
        params.put("method", method);
        //请求时间
        params.put("timeStamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        params.put("charset", "utf-8");
        //请求流水号
        params.put("reqId", String.valueOf(System.currentTimeMillis()));
        //发起方商户号，服务商在银盛给自己开设的商户号，即可当作发起方商户号，由银盛生成并下发。 注意：不同于子商户号，服务商发展的商户即为子商户号
        params.put("certId", isvParams.getCertId());
        //版本号，默认1.0，按接口文档来
        params.put("version", "1.1");

        return params;
    }

    /**
     * 公共参数
     **/
    public static TreeMap<String, String> buildMchBasicMap(YspayIsvParams isvParams,String method,String version,String notify_url){
        TreeMap<String, String> params = new TreeMap<String, String>();
        //接口方法名，根据接口文档取值
        params.put("method", method);
        //在银盛支付开设的服务商商户号，请联系客户经理提供
        params.put("partner_id", isvParams.getCertId());
        //请求时间
        params.put("timestamp", getCurrentDateTime("yyyy-MM-dd HH:mm:dd"));
        //固定utf-8
        params.put("charset", "utf-8");
        //报文签名算法，RSA、SM
        params.put("sign_type", "RSA");
        //版本号，默认1.0，按接口文档来
        params.put("version", version);
        // 交易成功异步通知到商户的后台地址，http路径支持多个url进行异步通知，多个url用分隔符“,”分开，格式如：url1,url2,url3，支持TLS1.0、TLS1.1、TLS1.2
        if(StrUtil.isNotEmpty(notify_url)){
            params.put("notify_url", notify_url);
        }

        return params;
    }

    public static String docheckRSA(YspayIsvParams isvParams,String key, com.alibaba.fastjson2.JSONObject authConfig) {
        String logPrefix = "【银盛商户】 - 生成对业务参数加密的密钥";
        String encryptKeyCheck = null;
        try {
            byte[] byte1= RSA256Util.encrypt(authConfig.getString("certFilePath"), ByteUtil.hexStringToBytes(key));
             encryptKeyCheck = Base64.getEncoder().encodeToString(byte1);
        } catch (Exception e) {
            log.info("{},方法docheckRSA，加密错误,错误信息：{},参数信息：isvParams={},key={}",logPrefix, e.toString(),JSONUtil.toJsonStr(isvParams),key);
        }
        return encryptKeyCheck;
    }

    public static String signMap(YspayIsvParams isvParams, Map<String,String> reqMap, com.alibaba.fastjson2.JSONObject authConfig) throws Exception {
        List<String> keys = new ArrayList<String>(reqMap.keySet());
        Collections.sort(keys);
        StringBuilder sb1 = new StringBuilder();
        for(String k : keys){
            if("sign".equals(k)) {
                continue;
            }
            sb1.append(k).append("=");
            sb1.append(reqMap.get(k));
            sb1.append("&");
        }
        if(sb1.length() > 0) {
            sb1.setLength(sb1.length() - 1);
        }
        //6.2使用接入方私钥对排序的请求参数加签，并存放到请求参数里面.privateFilePath:私钥地址，prvatePassword:私钥密钥
        String sign= RSA256Util.sign(sb1.toString(),authConfig.getString("certFilePath"),isvParams.getMercPrivateFilePassword());

        return sign;
    }



    /**
     * 参数签名
     **/
    public static String doEncryptionParam(JSONObject bizJSONObj,String key) {
        try {

            /** 5、使用生成的密钥key对业务参数进行加密，并将加密后的业务参数放入请求参数bizContent中*/
            byte[] bte = AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
            String msgBizContent = Base64.getEncoder().encodeToString(bte);
            return msgBizContent;
        } catch (Exception e) {
            log.info("加密错误,错误信息：{}", e.toString());
        }
        return null;
    }



    /**
     * 获取通知参数 公共方法
     *
     * **/
    public static TreeMap<String, String> getNotifyParams(HttpServletRequest request){
        TreeMap<String, String> treeMap = new TreeMap<String, String>();
        InputStreamReader in = null;
        try {
            in = new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8);
            StringBuffer bf = new StringBuffer();
            int len;
            char[] chs = new char[1024];
            while ((len = in.read(chs)) != -1) {
                bf.append(new String(chs, 0, len));
            }
            Map map = JSONObject.parseObject(bf.toString(), Map.class);
            log.debug("银盛异步回调参数转换：{}",JSONObject.toJSONString(map));
            for(Object m: map.entrySet()){
                String s = m.toString();
                log.info("s={}",s);
                String[] split = s.split("=",2);
                log.info("分开1：{}，2：{}",split[0],split[1]);
                treeMap.put(split[0],split[1]);
            }
            return treeMap;
        } catch (Exception e) {
            log.error("请求头部取数据异常：{}", e.getMessage());
            throw new ServiceException(e.getMessage());
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (Exception e) {
                    log.error("流关闭异常:{}", e.getMessage());
                }
            }
        }
    }

}
